/*
	File:	video/Drawing.hpp
	Date:	2013-06-01
	Author:	Asteroth
*/


#ifndef __ZEN_DRAWING_HPP__
#define __ZEN_DRAWING_HPP__

#include "Enabling.hpp"
#include "Texture.hpp"
#include "Font.hpp"

#include "../math.hpp"
#include "../gl.hpp"

namespace zen {

	namespace video {

		
		/**
		 * Drawing provides methods for 2D element drawing, it assumes that
		 * model view is identity and projection is orthogonal with an x and y
		 * expansion big enough to contain the drawn elements.
		 */
		class Drawing {


		public:

			static const glm::float32 DEFAULT_DEPTH; // = 0.0f;

			/**
				* Set the foreground color to be used by methods in this class that need a foreground color.
				* @param red		Red component of RGBA pixel format.
				* @param green		Green component of RGBA pixel format.
				* @param blue		Blue component of RGBA pixel format.
				* @param alpha		Alpha component of RGBA pixel format, default is 255 which is opaque.
				*/
			static void setColor(glm::u8 red, glm::u8 green, glm::u8 blue, glm::u8 alpha = 255);

			/**
				* Set the foreground color to be used by methods in this class that need a foreground color.
				* @param color A vector which contains the four RGBA channel values.
				*/
			static void setColor(const glm::u8vec4 &color);

			/**
				* The foreground color to be used by methods in this class that need a foreground color.
				* @return A vector which contains the four RGBA channel values.
				*/
			static glm::u8vec4 getColor();

			/**
				* Set the background color to be used by methods in this class that need a foreground color.
				* @param red		Red component of RGBA pixel format.
				* @param green		Green component of RGBA pixel format.
				* @param blue		Blue component of RGBA pixel format.
				* @param alpha		Alpha component of RGBA pixel format, default is 255 which is opaque.
				*/
			static void setBackColor(glm::u8 red, glm::u8 green, glm::u8 blue, glm::u8 alpha = 0);

			/**
				* Set the background color to be used by methods in this class that need a foreground color.
				* @param color A vector which contains the four RGBA channel values.
				*/
			static void setBackColor(const glm::u8vec4 &color);

			/**
				* The background color to be used by methods in this class that need a foreground color.
				* @return A vector which contains the four RGBA channel values.
				*/
			static glm::u8vec4 getBackColor();
		
			/**
				* Activates the current color.
				*/
			static void activateColor();
		
			/**
				* Activates the current background color.
				*/
			static void activateBackgroundColor();
		
			/**
				* Activates the restore color, usually white.
				*/
			static void restoreColor();

			/**
				* Set the line width used by methods in this class that need to draw lines.
				* @param width The width to be set, by default it is 1.0.
				*/
			static void setLineWidth(float width);

			/**
				* Get the line width used by methods in this class that need to draw lines.
				* @return The width value, by default it is 1.0.
				*/
			static float getLineWidth();

			/**
				* Enable or disable line smooth (antialias).
				* @param enable A boolean value which tells if the line smooth must be enabled or not.
				*/
			static void setLineSmoothEnabled(bool enable);

			/**
				* Checks if the line smooth is enabled.
				* @return A boolean which tells if the line smooth is enabled.
				*/
			static bool isLineSmoothEnabled();

			/**
				* Draws a line from point to point.
				* @param x1		X coordinate of the starting point.
				* @param y1		Y coordinate of the starting point.
				* @param x2		X coordinate of the ending point.
				* @param y2		Y coordinate of the ending point.
				* @param depth		Z coordinate of the drawing, can be used with depth test.
				*/
			static void drawLine(float x1, float y1, float x2, float y2, float depth = DEFAULT_DEPTH);

			/**
				* Draws a rectangle.
				* @param x			X coordinate of the top left rectangle.
				* @param y			Y coordinate of the top left rectangle.
				* @param width		Width of the rectangle.
				* @param height	Height of the rectangle.
				* @param fill		Tells if the rectangle should be filled.
				* @param depth		Z coordinate of the drawing, can be used with depth test.
				*/
			static void drawRectangle(float x, float y, float width, float height, bool fill = false, float depth = DEFAULT_DEPTH);

			/**
				* Draws an ellipse, can be used for circles by providing tha same width as height.
				* @param x			X coordinate of the center of the ellipse.
				* @param y			Y coordinate of the center of the ellipse.
				* @param width		Width of the ellipse.
				* @param height	Height of the ellipse.
				* @param fill		Tells if the ellipse should be filled.
				* @param depth		Z coordinate of the drawing, can be used with depth test.
				*/
			static void drawEllipse(float x, float y, float width, float height, bool fill = false, float depth = DEFAULT_DEPTH);

			/**
				* Rectangular texture draw.
				* @param texture	A texture created with zen::video::TextureManager
				* @param x			X coordinate of the top left rectangle.
				* @param y			Y coordinate of the top left rectangle.
				* @param width		Width of the rectangle.
				* @param height	Height of the rectangle.
				* @param depth		Z coordinate of the drawing, can be used with depth test.
				*/
			static void drawTexture(const PTexture &texture, float x, float y, float width, float height, float depth = DEFAULT_DEPTH);

			/**
				* Simple text draw.
				* @param font		A font created with zen::video::FontManager.
				* @param text		The text to be drawn.
				* @param x			X coordinate of the origin of the first character.
				* @param y			Y coordinate of the origin of the first character.
				* @param depth		Z coordinate of the drawing, can be used with depth test.
				*/
			static void drawText(const PFont &font, const std::string &text, float x, float y, float depth = DEFAULT_DEPTH);

			
		private:

			static glm::u8vec4 resColor;
			static glm::u8vec4 color;
			static glm::u8vec4 backColor;

		};


		inline void Drawing::setColor(glm::u8 red, glm::u8 green, glm::u8 blue, glm::u8 alpha) {
			color.r = red;
			color.g = green;
			color.b = blue;
			color.a = alpha;
		}


		inline void Drawing::setColor(const glm::u8vec4 &color) {
			Drawing::color = color;
		}

		inline glm::u8vec4 Drawing::getColor() {
			return color;
		}

		inline void Drawing::setBackColor(glm::u8 red, glm::u8 green, glm::u8 blue, glm::u8 alpha) {
			backColor.r = red;
			backColor.g = green;
			backColor.b = blue;
			backColor.a = alpha;
		}

		inline void Drawing::setBackColor(const glm::u8vec4 &color) {
			backColor = color;
		}

		inline glm::u8vec4 Drawing::getBackColor() {
			return backColor;
		}

		inline void Drawing::activateColor() {
			glColor4ubv(glm::value_ptr(color));
		}

		inline void Drawing::activateBackgroundColor() {
			glColor4ubv(glm::value_ptr(backColor));
		}

		inline void Drawing::restoreColor() {
			glColor4ubv(glm::value_ptr(resColor));
		}

		inline void Drawing::setLineWidth(float width) {
			glLineWidth(width);
		}

		inline float Drawing::getLineWidth() {
			float val;
			glGetFloatv(GL_LINE_WIDTH, &val);
			return val;
		}

		inline void Drawing::setLineSmoothEnabled(bool enable) {
			if (enable)
				Enable::lineSmooth();
			else
				Disable::lineSmooth();
		}

		inline bool Drawing::isLineSmoothEnabled() {
			return glIsEnabled(GL_LINE_SMOOTH) == GL_TRUE;
		}

		inline void Drawing::drawLine(float x1, float y1, float x2, float y2, float depth) {
			glBegin(GL_LINES);
				activateColor();
				glVertex3f(x1, y1, depth);
				glVertex3f(x2, y2, depth);
				restoreColor();
			glEnd();
		}


	} // namespace video

} // namespace zen

#endif // __ZEN_DRAWING_HPP__
